home *** CD-ROM | disk | FTP | other *** search
- /* Derived from fbbfwd.c */
-
- #include "global.h"
- #ifdef XFWD
- #include "ctype.h"
- #include "commands.h"
- #include "files.h"
- #include "bm.h"
- #include "reject.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: xfwd.c,v 1.22 1997/08/19 01:19:22 root Exp root $";
- #endif
-
- extern int MbForwarded, SYSOPprotect;
- extern int FWDpersonal, FWDbulletins;
- extern char FWDCall[AXALEN];
-
- extern int indexFwdBbs (char *name);
- extern void importcmd (int mode, char *bbsname);
- extern int bid_check (register char *string);
- extern char *nntp_name_expansion (char *name);
- extern void exitfwd (struct mbx *m);
- static int xdosy (struct fbbpacket *msglst,struct fwd *f,int msgcnt);
- static int doxrecv (struct fwd *f);
- static int doxsend (struct fwd *f, int firstsend);
- static int xfwdthisarea (struct fwd *, char *, int *, int *);
- static void sendEndOfXBlock (struct fwd *, int, int *, int *);
-
-
- #ifdef CATALOG
- #include "catalog.h"
-
- #define CAT xfwd_catalog
-
- #define forwardingto __STR(0)
- #define nodatatosend __STR(1)
- #define closingfwdfile __STR(2)
- #define processingarea __STR(3)
- #define sendingto __STR(4)
- #define sendingSXto __STR(5)
- #define badSY __STR(6)
- #define lostremote __STR(7)
- #define receivedSYfrom __STR(8)
- #define transferfailed __STR(9)
- #define errorgettingtemp __STR(10)
- #define errorxdosycode __STR(11)
- #define sendingmessageto __STR(12)
- #define refusing __STR(13)
- #define mailrefused __STR(14)
- #define transfersuccess __STR(15)
- #define mailsent __STR(16)
- #define receivecode __STR(17)
- #define sendingSY __STR(18)
- #define messagesreceived __STR(19)
- #define receivedfrom __STR(20)
-
- #else /* CATALOG */
- static const char forwardingto[] = "%sing X-forwarding of PBBS mail to: %s ";
- static const char nodatatosend[] = "XFWD: No Data to send. Sending F> to %s\n";
- static const char closingfwdfile[] = "XFWD: Closing .fwd file for %s.\n";
- static const char processingarea[] = "XFWD: Processing %s message area %s for %s.\n";
- static const char sendingto[] = "XFWD: Sending ( to %s ) to %s";
- static const char sendingSXto[] = "XFWD: Sending SX Block of %d to %s\n";
- static const char badSY[] = "XFWD Error: Expected 'SY ' string. Received '%s' string";
- static const char lostremote[] = "XFWD: Lost the remote connection with %s...\n";
- static const char receivedSYfrom[] = "XFWD: Received '%s' from %s\n";
- static const char transferfailed[] = "XFWD: Transfer failed with %s......\n";
- static const char errorgettingtemp[] =
- "XFWD: Error getting tmp file.\n"
- "XFWD: We're going to pass this file to sendmsg()\n"
- "XFWD: We were trying to open %s and failed.\n";
- static const char errorxdosycode[] = "XFWD: Error opening %s in xdosy() code.\n";
- static const char sendingmessageto[] = "XFWD: Sending message to %s\n";
- static const char refusing[] = "XFWD: Skipping message %s refused\n";
- static const char mailrefused[] = "XFWD: bbs mail refused: %s from %s";
- static const char transfersuccess[] = "XFWD: Transfer successful with %s\n";
- static const char mailsent[] = "PBBS mail sent: %s ";
- static const char receivecode[] = "XFWD: This is the receive code for %s.\n";
- static const char sendingSY[] = "XFWD: Sending our 'SY %d' response to %s.\n";
- static const char messagesreceived[] = "XFWD: Messages received (%d) from %s....\n";
- static const char receivedfrom[] = "XFWD: Received from %s - %s\n";
- #endif /* CATALOG */
-
-
- /* This code processes a SY packet from a remote system.
- Return = 0 means an error was detected.
- 1 means an 'F>' or '>' was received from the remote system.
- 2 means an 'Fx' (where x is something) was received.
- */
-
- static int xdosy (msglst, f, msgcnt)
- struct fbbpacket *msglst;
- struct fwd *f;
- int msgcnt;
- {
- int i, k;
- struct mbx *m;
- int incnt;
- char txtfile[80], *cp, *cp2;
- char tmp[AXBUF];
-
- m = f->m;
- /* Send any data in our buffer. */
- usflush (m->user);
-
- eatprompt:
- /* Get the SY line. */
- if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1 ) {
- if (Xtrace)
- tcmdprintf (lostremote, fwd_bbsname(m));
- return 0;
- }
-
- /* remove any line-end characters. */
- rip (m->line);
-
- if (Xtrace)
- tcmdprintf (receivedSYfrom, m->line, fwd_bbsname(m));
-
- /* Make sure we got a "SY " line. Anything else is an error. */
- if (strnicmp (m->line, "SY ", 3) != 0) {
- if (!m->fwdbbs->eatenanyprompts && !strcmp (">", m->line)) {
- m->fwdbbs->eatenanyprompts = 1;
- tcmdprintf ("XFWD: Eating a stray '>' (only allowed once) for %s\n", fwd_bbsname(m));
- goto eatprompt;
- }
- tprintf (badSY, m->line);
- tputs (".\n");
- if (Xtrace) {
- tcmdprintf(badSY, m->line);
- tcmdprintf(" from %s\n", fwd_bbsname(m));
- }
- return 0;
- }
-
- m->fwdbbs->eatenanyprompts = 1;
- incnt = atoi (&m->line[3]);
- /* Check to see if we got too many responses. */
- /* The next check makes sure we got enough of the right responses. */
- if(incnt > msgcnt)
- return 0;
-
- /* Validate SY line. Clean up unused entries. */
- for (i = 0; i < XMAXMSGS; i++) {
- msglst[i].accept = fbbNO;
- if (i >= msgcnt) {
- /* Zero out and free rest of the FS structure. */
- free (msglst[i].to);
- msglst[i].to = NULLCHAR;
- free (msglst[i].from);
- msglst[i].from = NULLCHAR;
- free (msglst[i].messageid);
- msglst[i].messageid = NULLCHAR;
- free (msglst[i].sline);
- msglst[i].sline = NULLCHAR;
- }
- }
-
- /* process the requested bid in the SY block */
- for (i = 0; i < incnt; i++) {
- if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
- if (Xtrace)
- tcmdprintf (transferfailed, fwd_bbsname(m));
- return 0;
- }
- rip (m->line);
- for (k = 0; k < msgcnt; k++) {
- if (!stricmp (m->line, msglst[k].bid)) {
- msglst[k].accept = fbbYES;
- break;
- }
- }
- }
-
- /* Now open the tempfile */
- (void) tmpnam (txtfile);
-
- if ((m->quickfile = fopen (txtfile, "w+b")) == NULLFILE) {
- tcmdprintf (errorgettingtemp, txtfile);
- if (Xtrace)
- log (m->user, errorxdosycode, txtfile);
- return 0;
- }
-
- /* The SY line is OK. Send the requested messages. */
- for (i = 0; i < msgcnt; i++) {
- kwait (NULL);
- MbForwarded++;
-
- if(msglst[i].accept == fbbYES) {
- /* Message is wanted. We need to send it.
- Do not update the X-Forwarded Header yet. X-fwd does not tell us
- if it received the message or not. We have to send all our
- messages and then see if the connect is still there. If we get
- a valid FBB Response, then we can assume that the messages were
- delivered and update the X-Forwarded flag. */
-
- if (Xtrace)
- tcmdprintf (sendingmessageto, fwd_bbsname(m));
- changearea (f->m, msglst[i].area, (int) 0);
-
- /* build From: line */
- strncpy (m->line, msglst[i].sline, MBXLINE);
- cp = strchr (m->line, '<');
- if (cp == NULLCHAR) /* shouldn't ever happen */
- continue;
- cp += 2;
- cp2 = strchr (cp, ' ');
- if (cp2 != NULLCHAR) /* also shouldn't ever happen */
- *cp2 = 0;
- fprintf (m->quickfile, "%s%s", Hdrs[FROM], cp);
-
- strncpy (m->line, msglst[i].bid, MBXLINE);
- cp = strpbrk (m->line, "_-");
- if (cp) {
- *cp = '@';
- fprintf (m->quickfile, "%s", cp);
- }
-
- /* build Message-Id: line */
- fprintf (m->quickfile, "\n%s<%lu@%s>\n", Hdrs[MSGID], m->mbox[msglst[i].number].bid,
- (*FWDCall) ? pax25(tmp,FWDCall) : pax25(tmp,Mycall));
-
- /* build To: line */
- strncpy (m->line, msglst[i].sline, MBXLINE);
- cp = strchr (&m->line[3], '@');
- if (cp == NULLCHAR) {
- cp = strchr (&m->line[3], ' ');
- if (cp != NULLCHAR)
- *cp = 0;
- fprintf (m->quickfile, "%s%s\n", Hdrs[TO], &m->line[3]);
- } else {
- *cp = 0;
- if (*(cp-1) == ' ')
- *(cp-1) = 0;
- if (*++cp == ' ')
- ++cp;
- cp2 = strchr (cp, ' ');
- if (cp2 != NULLCHAR)
- *cp2 = 0;
- fprintf (m->quickfile, "%s%s@%s\n", Hdrs[TO], &m->line[3], cp);
- }
-
- /* now the msgtype line */
- fprintf (m->quickfile, "%s%c\n", Hdrs[MSGTYPE], msglst[i].sline[1]);
- /* and the X-BID line */
- if (msglst[i].sline[1] == 'B' || ((msglst[i].sline[1] == 'P') && (!stricmp (msglst[i].area, "sysop") || !stricmp (&m->line[3], "sysop"))))
- fprintf (m->quickfile, "%s%s\n", Hdrs[XBID], msglst[i].bid);
- /* and finally the subject */
- fprintf (m->quickfile, "%s%s\n\n", Hdrs[SUBJECT], msglst[i].subject);
-
- /* Prepare the text of the message. */
- sendmsg(f->m, msglst[i].number, msglst[i].bid);
- fprintf (m->quickfile, "/EX\n");
- f->sentThisArea++;
-
- } else {
- /* The remote system does not want this message.
- Go ahead and mark the msg as so. If the link goes
- down, we still want to mark this message as unwanted.
- One the link goes back up, we do not want to ask the
- remote system again about this because it already
- told us no. */
- if (Xtrace)
- tcmdprintf (refusing, fwd_bbsname(m));
- /* mark message as forwarded or deleted. */
- mark_forwarded (msglst[i].fwdfile, msglst[i].fwdfileindex, '*');
- m->change |= CHG_READ;
- log (m->user, mailrefused, msglst[i].sline, fwd_bbsname(m));
- }
- }
-
- /* close the file. send_lzhuf() will re-open it. */
- (void) fclose (m->quickfile);
- m->quickfile = NULLFILE;
-
- /* And Send it. */
- if (incnt)
- (void) send_lzhuf(f, txtfile);
- else
- unlink (txtfile);
-
- /* Now we will get a line from the remote system to make sure that the
- messages were received ok. */
- usflush (m->user);
- if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
- /* There was a problem. We did not get a response from the remote
- system after we sent our messages. */
- if (Xtrace)
- tcmdprintf (transferfailed, fwd_bbsname(m));
- return 0;
- } else if (toupper(*m->line) == 'F' || *m->line == '>'){ /* only mark completed, if no garbage came in */
- if (Xtrace)
- tcmdprintf (transfersuccess, fwd_bbsname(m));
- /* We got a response back, so we can update our sent and unwanted messages. */
- for (i = 0; i < msgcnt; i++) {
- if (msglst[i].accept == fbbYES) {
- /* mark message as sent. */
- mark_forwarded (msglst[i].fwdfile, msglst[i].fwdfileindex, '*');
- m->change |= CHG_READ;
-
- log (m->user, mailsent, msglst[i].sline);
- #ifdef STATS_MSG
- STATS_addmsg(1, 1);
- #endif
- #ifdef STATS_TFC
- STATS_addtfc(3, 1);
- #endif
- #ifdef STATS_FWD
- STATS_addfwd(1, 1, m->name);
- #endif
- }
-
- if((!isarea (msglst[i].area) || msglst[i].type != 'B') && (stricmp(msglst[i].area, "sysop") || !SYSOPprotect)) {
- m->mbox[msglst[i].number].status |= BM_DELETE;
- statusCtl (msglst[i].area, "ctl", &m->mbox[msglst[i].number], msglst[i].number, 0);
- m->change |= CHG_DELETE;
- }
-
- free (msglst[i].to);
- msglst[i].to = NULLCHAR;
- free (msglst[i].from);
- msglst[i].from = NULLCHAR;
- free (msglst[i].messageid);
- msglst[i].messageid = NULLCHAR;
- free (msglst[i].sline);
- msglst[i].sline = NULLCHAR;
- }
- }
-
- if (strnicmp (m->line,"F>", 2) == 0 || *m->line == '>')
- return 1;
- else
- return 2;
- }
-
-
- /* returns 0 = okay, 1 = aborted, 2 = invalid data, 3 = lost connection, 4 = recv 'F>' */
- static int doxrecv(struct fwd *f)
- {
- int msgsize = 0;
- int i, k;
- char tempname[80], *cp;
- struct fbbpacket *msglst;
- struct mbx *m;
- int incnt = 0, mycnt = 0;
- int16 inchecksum, mychecksum;
- int retval = 0;
- #ifdef REJECT
- int rej;
- #endif
-
- msglst = f->msglst;
- m = f->m;
-
- if (Xtrace)
- tcmdprintf (receivecode, fwd_bbsname(m));
-
- if (!f->numtrans) {
- if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
- if (Xtrace)
- tcmdprintf (lostremote, fwd_bbsname(m));
- return 3;
- }
- rip (m->line);
- if (Xtrace)
- tcmdprintf (receivedfrom, fwd_bbsname (m), m->line);
- (void) strupr(m->line);
- if (!strnicmp ("F>", m->line, 2))
- return 4;
- if (strnicmp ("SX ", m->line, 3))
- return 2;
- incnt = atoi (&m->line[3]);
- } else {
- incnt = f->numtrans;
- f->numtrans = 0;
- }
-
- for (i = 0; i < XMAXMSGS; i++)
- msglst[i].accept = fbbNO;
-
- /* Loop till we have received a all X blocks. */
- for (k = 0; k < incnt; k++) {
- if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
- if (Xtrace)
- tcmdprintf (lostremote, fwd_bbsname(m));
- return 3;
- }
- kwait (NULL);
-
- if (cutofffwding (m))
- return 3;
-
- /* strip any trailing NL characters. */
- rip(m->line);
-
- if (Xtrace)
- tcmdprintf (receivedfrom, fwd_bbsname(m), m->line);
- log (m->user, "XFWD %s: %s", fwd_bbsname(m), m->line);
-
- #ifdef REJECT
- rej = reject (m->line, 1, 1);
- if (rej != REJ_REJECT && rej != REJ_DEFER)
- #endif
- if (!bid_check (m->line))
- strncpy (msglst[mycnt++].bid, m->line, 15);
-
- }
-
-
- if (Xtrace)
- tcmdprintf (sendingSY, mycnt, fwd_bbsname(m));
- tprintf ("SY %d\n", mycnt);
- for (k = 0; k < mycnt; k++)
- tprintf ("%s\n", msglst[k].bid);
- usflush(m->user);
-
- if (mycnt) {
- /* receive the SS block, with the compressed data size */
- if (recvline (m->user, (unsigned char *)m->line, MBXLINE) == -1) {
- if (Xtrace)
- tcmdprintf (lostremote, fwd_bbsname(m));
- return 3;
- }
- if (Xtrace)
- tcmdprintf (receivedfrom, fwd_bbsname(m), m->line);
- msgsize = atoi (&m->line[3]);
- cp = skipnonwhite (&m->line[3]);
- cp = skipwhite (cp);
- inchecksum = (int16) atol (cp);
-
- /* The remote system will start sending the message data. */
- /* Set up a temp name to receive the file. */
- sprintf (tempname, "%s/%s.imp", IMPORTDir, m->name);
-
- /* Receive the messages and uncompress them. */
- strncpy (f->iFile, tmpnam(NULL), FWDFILELEN);
- strncpy (f->oFile, tempname, FWDFILELEN);
- if (recv_lzhuf(f, msgsize, &mychecksum) == 0)
- return 1;
- if (inchecksum != mychecksum) {
- if (Xtrace)
- tcmdprintf ("XFWD: Checksum error with %s: received %u, calculated %u\n", fwd_bbsname(m), inchecksum, mychecksum);
- retval = 1;
- unlink (f->oFile);
- } else
- importcmd (0, m->name);
- /* remove the other file */
- unlink (f->iFile);
-
- if (Xtrace && !retval)
- tcmdprintf (messagesreceived, mycnt, fwd_bbsname(m));
- }
- return retval;
- }
-
-
- /****************************************************************************************/
- /* This code is called when we've 25 X-Blocks, or we don't have any more */
- /* messages to send. */
- /****************************************************************************************/
- static void sendEndOfXBlock (f, msgcnt, Xok, Xdone)
- struct fwd *f;
- int msgcnt, *Xok, *Xdone;
- {
- int rc;
- struct mbx *m;
- struct fbbpacket *msglst;
-
- /* point pointers to their proper location. */
- msglst = f->msglst;
- m = f->m;
-
- if (Xtrace)
- tcmdprintf (sendingSXto, msgcnt, fwd_bbsname(m));
- tprintf ("SX %d\n", msgcnt);
- for (rc = 0; rc < msgcnt; rc++)
- tprintf ("%s\n", msglst[rc].bid);
-
- /* Process an incoming SY and receive messages. */
- rc = xdosy(msglst, f, msgcnt);
- if (!rc) {
- *Xok = FALSE;
- *Xdone = TRUE;
- } else if (rc == 1) {
- *Xok = TRUE;
- *Xdone = FALSE;
- } else if (rc == 2) {
- *Xok = TRUE;
- *Xdone = TRUE;
- }
- }
-
-
- /****************************************************************************************/
- /* This code is called for each message area we forward to. */
- /****************************************************************************************/
- static int xfwdthisarea (f, area, Xok, Xdone)
- struct fwd *f;
- char *area;
- int *Xok, *Xdone;
- {
- char line[MBXLINE];
- int err = 0;
- int msgcnt = 0;
- int Tmsgcnt = 0;
- int theindex = 0;
- int changed = 0;
- int rc, i;
- long bid;
- long curpos;
- long tempsize;
- char *pszBid;
- long msgsize = 0;
- #if 0
- int passes = 0;
- #endif
-
- struct let *cmsg;
- struct mbx *m;
- struct fbbpacket *msglst;
-
- /* for makecl() */
- int bulletin;
- char *newto = NULLCHAR;
- char line2[64];
- char thebid[LINELEN];
- char subject[LINELEN];
- struct arealist *a;
-
-
- /* point pointers to their proper location. */
- msglst = f->msglst;
- m = f->m;
-
- /* public area? */
- bulletin = isarea (area);
-
- if (Xtrace && FWDareatrace)
- tcmdprintf (processingarea, bulletin ? "Public " : "Private ", area, fwd_bbsname(m));
-
- /* Initialize variables. */
- *Xok = TRUE;
- *Xdone = FALSE;
-
- if (bulletin && (!FWDbulletins || !m->fwdbbs->bulletins)) {
- if (Xtrace)
- tcmdprintf ("Skipping any bulletins in area '%s' for %s\n", area, m->fwdbbs->name);
- return Tmsgcnt;
- }
- if (!bulletin && (!FWDpersonal || !m->fwdbbs->personals)) {
- if (Xtrace)
- tcmdprintf ("Skipping any personal messages in area '%s' for %s\n", area, m->fwdbbs->name);
- return Tmsgcnt;
- }
-
- /* check if there are any messages in this area that need to be forwarded. */
- rewind (f->fwdfile); /* rewind forward file... */
- curpos = 0L; /* set file position */
- /* read each line in the .fwd file. exit loop on error or no more lines */
- while (!err && fgets (line, MBXLINE, f->fwdfile) != NULLCHAR) {
- (void) fflush (f->fwdfile);
- kwait (NULL); /* Give control back to system. */
- if (*line != '*' && *line != '!' && *line != '-') { /* '*' means this has been done */
- /* '!' means this is blocked */
- /* '-' means this was sent to an ALT BBS */
- if ((pszBid = strpbrk(&line[1], " \t")) != NULLCHAR) /* get the bid. */
- *pszBid++ = '\0';
- else
- continue; /* improperly formatted */
- if (!stricmp (area, &line[1])) { /* is this the correct area? */
- bid = atol (pszBid); /* get the message number */
- if (!changed) { /* are we in the right area... */
- m->area[0] = 0; /* force a reload of index */
- changearea(m, area, (int) 0); /* if not... go there now... */
- changed = 1; /* and update the flag....*/
- }
- /* Set the 'found message flag' to false. */
- theindex = 0;
- /* for each message in the .txt file... */
- for (cmsg = &m->mbox[1], i = 1; i <= m->nmsgs; i++, cmsg++)
- /* find the message we're supposed to forward. */
- if ((bid == cmsg->bid) && !(cmsg->status & BM_DELETE)) {
- /* this is the message... set the flag and break. */
- theindex = i;
- break;
- }
-
- if (theindex && m->fwdbbs && m->fwdbbs->maxsize && cmsg->size > m->fwdbbs->maxsize) {
- if (Xtrace)
- tcmdprintf ("XFWD: Deferring large message to %s, allowed=%ld, size=%ld\n", m->fwdbbs->name, m->fwdbbs->maxsize, cmsg->size);
- } else {
- /* if we didn't find the message... it must have been deleted. We can */
- /* mark the message as forwarded so we don't try it again. This is just */
- /* done for performance reasons. */
- /* Also, if found, block it. Then if an I/O error occurs, this message */
- /* will be skipped until all others have a chance to get passed */
- mark_forwarded (f->fwdfile, curpos, (!theindex) ? '*' : '!');
-
- /* if the 'found message flag' is set.... */
- if (theindex && !(cmsg->status & (BM_ONHOLD | BM_DELETE))) {
- newto = NULLCHAR; /* just in case */
- if (m->fwdbbs) /* just in case */
- for (a = m->fwdbbs->areas; a; a = a->next)
- if (!stricmp (area, a->name))
- newto = a->forceaddr;
-
- /* Prepare the FB line. */
- bulletin = isarea (area); /* reset, just in case */
- rc = makecl(m, theindex, newto, line2, subject, thebid, &bulletin);
- if (rc == -2) { /* delete the message */
- mark_forwarded (f->fwdfile, curpos, '*');
- if ((!isarea (area) || m->stype != 'B') && (stricmp (area, "sysop") || !SYSOPprotect)) {
- m->mbox[i].status |= BM_DELETE;
- statusCtl (area, "ctl", &m->mbox[i], i, 0);
- m->change |= CHG_DELETE;
- }
- } else if (rc != -1) { /* If command line ok, store it. */
- /* Copy SEND line for message log. */
- free (msglst[msgcnt].sline);
- (void) strupr (msglst[msgcnt].sline = strdup (line2));
- msglst[msgcnt].fwdfileindex = curpos;
- msglst[msgcnt].fwdfile = f->fwdfile;
-
- /* store the message type */
- msglst[msgcnt].type = msglst[msgcnt].sline[1];
-
- /* Keep track of the subject. */
- free (msglst[msgcnt].subject);
- msglst[msgcnt].subject = strdup (subject);
-
- /* Keep track of the message area */
- free (msglst[msgcnt].area);
- msglst[msgcnt].area = strdup (area);
-
- /* Keep track of message number in area. */
- msglst[msgcnt].number = i;
-
- /* Keep track of makecl() modified bid. */
- strncpy (msglst[msgcnt].bid, &thebid[1], 15);
-
- if (Xtrace)
- tcmdprintf (sendingto, fwd_bbsname(m), line2);
-
- msgcnt++;
- msgsize += m->mbox[theindex].size;
- /* If we have filled our SX Block */
- if (msgcnt >= XMAXMSGS || (m->fwdbbs && m->fwdbbs->fbbsize && msgsize > m->fwdbbs->fbbsize)) {
- sendEndOfXBlock (f, msgcnt, Xok, Xdone);
- Tmsgcnt += msgcnt;
- msgcnt = 0;
- msgsize = 0;
- }
- }
- }
- }
- }
- } /* end if() */
- /* If we got an error from dofs() or the response
- from dofs() was 2, we are done with this message
- transfer. If we got a 1 from dofs() we can send
- more messages now so we do not need to exit. */
- if (*Xdone)
- break;
- curpos = ftell (f->fwdfile); /* get file position */
- tempsize = m->mysize;
- if(isnewprivmail (m, "fwd") > 0) {
- m->mysize = tempsize;
- break;
- }
- } /* end while() */
-
- /* If we have any left over messages... send them now. */
- if (msgcnt) {
- sendEndOfXBlock (f, msgcnt, Xok, Xdone);
- Tmsgcnt += msgcnt;
- }
-
- return Tmsgcnt;
- }
-
-
- /* This code is used to figure out what messages need to be sent. */
- static int doxsend (f, firstsend)
- struct fwd *f;
- int firstsend;
- {
- int err = 0;
- int Tmsgcnt;
- int Xdone;
- int Xok = 0;
- long pos;
- char name[256];
- struct arealist *fwdarea;
- struct mbx *m;
- int areasused;
- int equals, bang;
-
- /* point pointers to their proper location. */
- m = f->m;
-
- /* figure out name of the user. */
- sprintf (name, "%s/%s", Mailspool, m->name);
- (void) nntp_name_expansion (name);
-
- /* Save data */
- strncpy (f->savefsline, m->line, MBXLINE);
-
- /* figure out .fwd file name and see if it exist. It it doesn't exist... */
- /* .... we have nothing for this user. */
- strcat (name, ".fwd");
- (void) strlwr (name);
- if ((f->fwdfile = fopen (name, UPDATE_TEXT)) == NULLFILE)
- /* the file doesn't exist. This should only occur with a reverse forward request. */
- return 2;
-
- /* Check to see if we have any info to send and make sure it is the
- right time to send data. */
- if (!f->m->fwdbbs && fwdinit (f->m, 1) == -1)
- /* The bbs is not in the forward.bbs file or it is the wrong time to send.
- Return a 0 to indicate that we have no data for the remote system. */
- return 0;
-
- /* Now grab a subchannel slot, if needed. It is available, or fwdinit()
- would have returned -1. */
- (void) checksubchannel (m, 1);
-
- /* restore data. */
- strncpy(m->line, f->savefsline, MBXLINE);
-
- checkloop:
- kwait (NULL);
-
- /* Initialize the fwdarea pointer. This is the list of areas we forward to. */
- fwdarea = m->fwdbbs->areas;
-
- /* for each area in the fwdarea list do.... */
- err = 0;
- Tmsgcnt = 0;
- areasused = 0;
- (void) isnewprivmail (m, "fwd"); /* first time, just sets m->mysize */
- while (!err && fwdarea) {
-
- kwait (NULL);
- if (cutofffwding (m)) {
- Xok = 0;
- break;
- }
-
- f->sentThisArea = 0;
- Tmsgcnt += xfwdthisarea (f, fwdarea->name, &Xok, &Xdone);
- if (Xdone || Tmsgcnt)
- break;
- if (isnewprivmail (m, "fwd") > 0)
- goto checkloop;
- if (f->sentThisArea) /* if we got something in this area */
- areasused += 1;
- fwdarea = fwdarea->next; /* Do next area. */
- } /* end while() */
-
- if (!Xok) { /* We had an error. */
- (void) fclose (f->fwdfile);
- return 3;
- }
-
- /* this next piece (and the sections above that affect areasused), make
- this go BACK to check for messages added into earlier areas. This
- prevents us from disconnecting if some new info JUST came in. */
- if (areasused)
- goto checkloop;
-
- if (Xtrace)
- tcmdprintf (closingfwdfile, fwd_bbsname(m));
-
- /* See if we can remove the .fwd file. */
- fwdlockit (m->name);
- rewind (f->fwdfile);
- equals = 0;
- bang = 0;
- while (pos = ftell (f->fwdfile), fgets (f->line, MBXLINE, f->fwdfile) != NULLCHAR) {
- kwait (NULL);
- if (*f->line == '=') {
- mark_forwarded(f->fwdfile, pos, '!');
- equals++;
- err = 1;
- } else if (*f->line == '!') {
- mark_forwarded(f->fwdfile, pos, ' ');
- bang++;
- err = 1;
- } else if(*f->line != '*' && *f->line != '-') { /* if not already done */
- err = 1;
- #if 0
- break;
- #endif
- }
- }
-
- if (firstsend && !Tmsgcnt && bang && !equals) {
- /* we didn't transfer any messages, there seems to have been all
- messages marked with '!', so we will re-scan */
- if (Xtrace)
- tcmdprintf ("XFWD: Relooping on .fwd file for %s - 1st scan since last aborted session\n", fwd_bbsname(m));
- fwdunlockit (m->name);
- goto checkloop;
- }
-
- /* one last check, to avoid deleting a file that JUST added a record */
- if (isnewprivmail (m, "fwd") > 0) {
- if(Xtrace)
- tcmdprintf ("XFWD: Relooping on .fwd file for %s - new messages received\n", fwd_bbsname(m));
- fwdunlockit (m->name);
- goto checkloop;
- }
-
- (void) fclose (f->fwdfile);
- if (!err)
- (void) remove (name);
-
- fwdunlockit (m->name);
- kwait (NULL);
- if (!Tmsgcnt)
- /* We had no data. */
- return 2;
- return 1;
- }
-
-
- /* This is the main entry point for X-forwarding. */
- int
- doxfwd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct fwd f;
- struct mbx *m;
- struct fbbpacket *msglst;
- int i;
- int firstsend = 1;
- int Done;
- int rc;
- int FBBRdone = FALSE; /* Receiving system has no more data. */
- int NeedData;
- int X_fwd;
-
-
- f.m = (struct mbx *)p;
- m = f.m;
-
- log (f.m->user, forwardingto, (argc) ? "Incom" : "Outgo", m->name);
-
- /* First verify that this is a system that supports X-forwarding. */
- if(!(f.m->sid & MBX_XFWD)) {
- tputs ("Huh?\n");
- usflush (m->user);
- return -1;
- }
-
- /* Get memory for the msglst array. */
- f.msglst = (struct fbbpacket *)callocw ((unsigned)XMAXMSGS, sizeof(struct fbbpacket));
- m->msglst = msglst = f.msglst;
-
- NeedData = FALSE;
- Done = FALSE;
- X_fwd = FALSE;
-
- /* See if we were called because we received a SX from the remote system. */
- if (!argc) {
- f.m->state = MBX_FORWARD; /* We are in send mode. */
- FBBRdone = FALSE;
- NeedData = TRUE;
- X_fwd = TRUE;
- } else if(argv[0][0] == 'S' && m->stype == 'X') {
- if (argc != 2) {
- tputs ("Huh?\n");
- usflush (m->user);
- Done = TRUE;
- } else {
- f.numtrans = (char) atoi (argv[1]);
- /* indicate that we are in receive mode. */
- f.m->state = MBX_REVFWD;
- FBBRdone = FALSE;
- }
- } else {
- /* Must have received a F> from the remote system. */
- f.m->state = MBX_FORWARD; /* We are in send mode. */
- FBBRdone = TRUE;
- }
-
-
- if(Xtrace)
- tcmdprintf ("XFWD: %sing forwarding started with %s.\n", (argc) ? "Incom" : "Outgo", fwd_bbsname(m));
-
- while (!Done) {
- kwait (NULL);
- if (f.m->state == MBX_REVFWD) {
- if (Xtrace)
- tcmdprintf ("XFWD: Receiving data from %s.\n", fwd_bbsname(m));
-
- if (NeedData) { /* null out the line. */
- f.m->line[0] = 0;
- f.numtrans = 0;
- }
-
- NeedData = TRUE;
- /* Receive data from remote system. Process SX block. */
- rc = doxrecv (&f);
- if (rc == 4) { /* Remote system sent us a F> */
- if (X_fwd)
- Done = TRUE;
- else /* Change status. */
- f.m->state = MBX_FORWARD;
- FBBRdone = TRUE;
- } else if (rc)
- Done = TRUE;
- if (Done != TRUE) {
- tputs ((X_fwd == TRUE) ? "F>\n" : ">\n");
- if (Xtrace)
- tcmdprintf ("XFWD: Sending '%s>' to %s\n",
- (X_fwd == TRUE) ? "F" : "", fwd_bbsname(m));
- usflush (m->user);
- }
- } else {
- if (Xtrace)
- tcmdprintf ("XFWD: Sending data to %s.\n", fwd_bbsname(m));
-
- NeedData = FALSE;
- /* Change status. */
- rc = doxsend (&f, firstsend);
- firstsend = 0;
- if (rc == 3) /* An error occured. */
- break;
- if ((rc == 0) || (rc == 2)) {
- /* We had no data for remote system. */
- if (FBBRdone) {
- /* They have no more data for us....
- So we break out of this loop and disconnect.
- */
- break;
- } else {
- /* Tell them that we do not have any data for them. */
- if(Xtrace)
- tcmdprintf (nodatatosend, fwd_bbsname(m));
- tputs ("F>\n");
- /* Change status. */
- f.m->state = MBX_REVFWD;
- usflush (m->user);
- NeedData = TRUE;
- }
- }
- }
- } /* endwhile */
-
- /* free anything in the msglst array. */
- for (i = 0; i < XMAXMSGS ; i++) {
- free (msglst[i].to);
- free (msglst[i].from);
- free (msglst[i].messageid);
- free (msglst[i].sline);
- msglst[i].to = msglst[i].from = msglst[i].messageid = msglst[i].sline = NULLCHAR;
- }
-
- /* Now free the msglst array. */
- free (msglst);
-
- usflush (m->user);
- releasesubchannel (m); /* just in case */
- if (X_fwd) {
- exitfwd(m);
- return 0;
- } else {
- /* This section marks the last fwd session time */
- if ((i = indexFwdBbs (fwd_bbsname(m))) != NUMFWDBBS) {
- MyFwds[i].laston = time (NULL);
- MyFwds[i].lastactivity = time (NULL);
- }
- m->state = MBX_CMD;
- return domboxbye(0,NULL,m);
- }
- }
-
- #endif /* ifdef XFWD */
-
-